﻿using System;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Threading;
using Vtron.ATSP.DomainObjects;

namespace Vtron.ATSP.Infrastructure
{
    /// <summary>
    /// 串口通信类
    /// </summary>
    /// <remarks>
    ///     <创建人>邓穗捷</创建人>
    ///     <创建时间>2014-08-22</创建时间>
    ///     <修订人></修订人>
    ///     <修订时间></修订时间>
    ///     <修订说明></修订说明>
    /// </remarks>
    public class SerialHandler : ISerialHandler
    {
        /// <summary>
        /// 检查端口连接
        /// </summary>
        /// <param name="portName">要使用的端口（例如 COM1）</param>
        /// <param name="baudRate">波特率</param>
        /// <returns>
        /// 是否连接成功 
        ///     true:成功
        ///     false:失败
        /// </returns>
        /// <remarks>
        ///     <创建人>邓穗捷</创建人>
        ///     <创建时间>2014-08-22</创建时间>
        ///     <修订人></修订人>
        ///     <修订时间></修订时间>
        ///     <修订说明></修订说明>
        /// </remarks>
        public bool CheckCOM(string portName, int baudRate)
        {
            bool result = false;
            try
            {
                SerialPort sp = new SerialPort(portName);
                sp.Close();
                sp.Open();
                sp.Close();
                result = true;
            }
            catch
            {
                result = false;
            }

            return result;
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="portName">要使用的端口（例如 COM1）</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="parity">奇偶校验值</param>
        /// <param name="dataBits">标准数据位长度</param>
        /// <param name="stopBits">停止位数</param>
        /// <param name="readTimeout">超时时间（毫秒）</param>
        /// <param name="sendData">需要发送的数据</param>
        /// <returns>命令返回的数据</returns>
        /// <remarks>
        ///     <创建人>邓穗捷</创建人>
        ///     <创建时间>2014-08-22</创建时间>
        ///     <修订人></修订人>
        ///     <修订时间></修订时间>
        ///     <修订说明></修订说明>
        /// </remarks>
        public byte[] Send(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits, int readTimeout, byte[] sendData)
        {
            if (!(SerialPort.GetPortNames().Any(t => t == portName)))
            {
                throw new IOException(String.Format("未能找到端口：{0}", portName));
            }

            SerialPort sp = new SerialPort();
            sp.PortName = portName;
            sp.BaudRate = baudRate;
            sp.Parity = parity;
            sp.DataBits = dataBits;
            sp.StopBits = stopBits;
            sp.ReadTimeout = readTimeout;
            sp.ReadBufferSize = 1024;
            sp.WriteBufferSize = 512;

            try
            {
                sp.Close();
                if (!sp.IsOpen)
                {
                    sp.Open();
                }
            }
            catch (Exception ex)
            {
                throw new ATSPException("打开串口时发生错误，错误信息：" + ex.Message);
            }

            sp.DiscardInBuffer();
            sp.DiscardOutBuffer();

            try
            {
                sp.Write(sendData, 0, sendData.Length);
            }
            catch (Exception ex)
            {
                if (sp.IsOpen)
                {
                    sp.Close();
                }

                throw new ATSPException("上传数据时发生错误，错误信息：" + ex.Message);
            }

            Thread.Sleep(600);

            int dataLen = sp.BytesToRead;
            byte[] receivedData = new byte[dataLen];
            try
            {
                sp.Read(receivedData, 0, dataLen);
            }
            catch (Exception ex)
            {
                throw new ATSPException("接收数据时发生错误，错误信息：" + ex.Message);
            }
            finally
            {
                if (sp.IsOpen)
                {
                    sp.Close();
                }
            }

            return receivedData;
        }
    }
}
